import CryptoJS from 'crypto-js';
import JSEncrypt from 'jsencrypt';

export const Base64 = {
  encode: (plainText: string): string => {
    return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(plainText));
  },
  decode: (encodedText: string): string => {
    return CryptoJS.enc.Base64.parse(encodedText).toString(CryptoJS.enc.Utf8);
  },
};

export const SHA256 = {
  digest: (text: string) => {
    return CryptoJS.SHA256(text).toString().toUpperCase();
  },
};

export const MD5 = {
  digest: (text: string) => {
    return CryptoJS.MD5(text).toString().toUpperCase();
  },
};

const appKey = import.meta.env.VITE_SIGN_APP_KEY;
const secretKey = import.meta.env.VITE_SIGN_SECRET_KEY;
const encryptKey = import.meta.env.VITE_ENCRYPT_SECRET_KEY;
const enableEncryptBody = import.meta.env.VITE_ENCRYPT_BODY_ENABLE;

const jsEncrypt = new JSEncrypt();
jsEncrypt.setPrivateKey(secretKey);
export const Sign = {
  sign: (text: string) => {
    return jsEncrypt.sign(text, CryptoJS.SHA256, 'RSA-SHA256');
  },
};

export const ParameterDataSecure = {
  decryptBody: (text: string) => {
    const wordArrayKey = CryptoJS.enc.Base64.parse(encryptKey);
    const decrypted = CryptoJS.AES.decrypt(text, wordArrayKey, {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7,
    });
    return decrypted.toString(CryptoJS.enc.Utf8);
  },
  sign: (config) => {
    if (!appKey || !secretKey) {
      return;
    }
    const timesTamp = Date.now();
    const parameters = `{"alg":"MD5","appKey":"${appKey}","timestamp":"${timesTamp}"}`;
    const parametersBase64 = Base64.encode(parameters);
    let path = config.url;
    if (path.slice(0, 1) !== '/') {
      path = `/${path}`;
    }
    let body = config.data ? JSON.stringify(config.data) : '';
    if (enableEncryptBody === 'true' && body) {
      const wordArrayKey = CryptoJS.enc.Base64.parse(encryptKey);
      const encrypted = CryptoJS.AES.encrypt(body, wordArrayKey, {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7,
      });
      const encryptBody = encrypted.toString();

      body = JSON.stringify(encryptBody);
      config.data = encryptBody;
    }

    const dataToSign = `${parametersBase64}${path}${body}`;

    const sign = `${parametersBase64}.${Sign.sign(dataToSign)}`;

    config.headers['X-PROTECT'] = sign;
  },
};
